package com.hskn.hss.module.tlempsalary.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hskn.hss.core.annotation.DataScope;
import com.hskn.hss.core.utils.LoginUtils;
import com.hskn.hss.entity.AjaxResult;
import com.hskn.hss.exception.ExcelReaderDataException;
import com.hskn.hss.exception.HssException;
import com.hskn.hss.module.depart.entity.SysDepart;
import com.hskn.hss.module.depart.mapper.SysDepartMapper;
import com.hskn.hss.module.depart.service.ISysDepartService;
import com.hskn.hss.module.tlemployee.entity.TlEmployee;
import com.hskn.hss.module.tlemployee.mapper.TlEmployeeMapper;
import com.hskn.hss.module.tlemployee.service.ITlEmployeeService;
import com.hskn.hss.module.tlempsalary.entity.TlEmpSalary;
import com.hskn.hss.module.tlempsalary.mapper.TlEmpSalaryMapper;
import com.hskn.hss.module.tlempsalary.service.ITlEmpSalaryService;
import com.hskn.hss.module.tlempsalary.to.*;
import com.hskn.hss.module.tlopetation.entity.TlOperation;
import com.hskn.hss.module.tlopetation.service.ITlOperationService;
import com.hskn.hss.module.tlworktype.entity.TlWorkType;
import com.hskn.hss.module.userdepart.entity.SysUserDepart;
import com.hskn.hss.module.userdepart.mapper.SysUserDepartMapper;
import com.hskn.hss.module.worktype.service.IWorkTypeService;
import com.hskn.hss.to.ForIdsTO;
import com.hskn.hss.utils.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hskn
 * @since 2021-05-19
 */
@Service
public class TlEmpSalaryServiceImpl extends ServiceImpl<TlEmpSalaryMapper, TlEmpSalary> implements ITlEmpSalaryService {

    @Resource
    TlEmpSalaryMapper tlEmpSalaryMapper;
    @Resource
    SysUserDepartMapper sysUserDepartMapper;
    @Resource
    SysDepartMapper sysDepartMapper;
    @Resource
    TlEmployeeMapper employeeMapper;
    @Resource
    ITlEmployeeService employeeService;
    @Resource
    private SysDepartMapper departMapper;
    @Resource
    private ISysDepartService departService;
    @Resource
    private IWorkTypeService workTypeService;
    @Resource
    private ITlOperationService tlOperationService;

    @Override
    public AjaxResult insert(TlEmpSalaryInsertTO tlEmpSalaryInsertTO) throws HssException {
        String uid = LoginUtils.getUser().getUid();
        TlEmpSalary tlEmpSalary = new TlEmpSalary();
        BeanUtils.copyProperties(tlEmpSalaryInsertTO, tlEmpSalary);
        QueryWrapper<SysUserDepart> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysUserDepart::getUserid, uid);
        String deptid = sysUserDepartMapper.selectOne(queryWrapper).getDepid();
        tlEmpSalary.setCreateby(uid);
        tlEmpSalary.setCreatetime(new Date());
        tlEmpSalary.setEmpdeptid(deptid);
        if (StringUtils.isNotEmpty(tlEmpSalary.getEmpid())) {
            TlEmployee employee = employeeMapper.selectById(tlEmpSalary.getEmpid());
            if (employee != null) {
                tlEmpSalary.setWorkType(employee.getWorktype());
                tlEmpSalary.setOperationId(employee.getPersontype());
                tlEmpSalary.setEmpdeptid(employee.getDeptid());
            }
        }
        int i = tlEmpSalaryMapper.insert(tlEmpSalary);
        boolean flag = i > 0;
        if (flag) {
            return AjaxResult.success("操作成功");
        } else {
            return AjaxResult.fail("操作失败，请稍后再试");
        }
    }

    @Override
    public AjaxResult update(TlEmpSalaryUpdateTO salaryTO) throws HssException {

        String uid = LoginUtils.getUser().getUid();
        TlEmpSalary tlEmpSalary = new TlEmpSalary();
        BeanUtils.copyProperties(salaryTO, tlEmpSalary);
        tlEmpSalary.setUpdateby(uid);
        tlEmpSalary.setUpdatetime(new Date());
        if (StringUtils.isNotEmpty(tlEmpSalary.getEmpid())) {
            TlEmployee employee = employeeMapper.selectById(tlEmpSalary.getEmpid());
            if (employee != null) {
                tlEmpSalary.setWorkType(employee.getWorktype());
                tlEmpSalary.setOperationId(employee.getPersontype());
                tlEmpSalary.setEmpdeptid(employee.getDeptid());
            }
        }
        int i = tlEmpSalaryMapper.updateById(tlEmpSalary);
        boolean flag = i > 0;
        if (flag) {
            return AjaxResult.success("操作成功");
        } else {
            return AjaxResult.fail("操作失败，请稍后再试");
        }
    }

    @Override
    public AjaxResult deletebyid(ForIdsTO forIdsTO) throws HssException {
        tlEmpSalaryMapper.deleteBatchIds(forIdsTO.getIds());
        return AjaxResult.success("操作成功");
    }

    @Override
    public TlEmpSalary getDetail(TlEmpSalaryDetailTO salaryTO) throws HssException {
        TlEmpSalary tlEmpSalary = tlEmpSalaryMapper.selectById(salaryTO.getId());
        SysDepart depart = sysDepartMapper.selectById(tlEmpSalary.getEmpdeptid());
        TlEmployee employee = employeeMapper.selectById(tlEmpSalary.getEmpid());
        if (employee != null) {
            tlEmpSalary.setEmpName(employee.getName());
        }
        if (depart != null) {
            tlEmpSalary.setEmpdeptName(depart.getDepartName());
        }
        return tlEmpSalary;
    }

    @Override
    @DataScope(deptAlias = "empdeptid", userAlias = "createby")
    public JSONObject getList(TlEmpSalaryListTO salaryTO) throws HssException {
        JSONObject json = new JSONObject();
        Map<String, TlWorkType> workTypeMap = workTypeService.getWorkTypeMap(new QueryWrapper<>());
        Map<String, TlOperation> operationMap = tlOperationService.getTlOperationMap(new QueryWrapper<>());
        Map<String, SysDepart> departMap = departService.getDepartMap(new QueryWrapper<>());
        QueryWrapper<TlEmpSalary> empSalaryQueryWrapper = new QueryWrapper<>();
        QueryWrapper<TlEmployee> employeeQueryWrapper = new QueryWrapper<>();
        Map<String, TlEmployee> employeeMap = null;
        if (StringUtils.isNotEmpty(salaryTO.getName()) || StringUtils.isNotEmpty(salaryTO.getIdcard()) || StringUtils.isNotEmpty(salaryTO.getCardnum())) {
            employeeQueryWrapper.lambda().eq(TlEmployee::getName, salaryTO.getName());
            employeeQueryWrapper.lambda().eq(TlEmployee::getIdcardnum, salaryTO.getIdcard());
            employeeQueryWrapper.lambda().eq(TlEmployee::getEmplnum, salaryTO.getCardnum());
            employeeMap = employeeService.getEmpMap(employeeQueryWrapper);
        }
        if (null != employeeMap) {
            empSalaryQueryWrapper.lambda().eq(TlEmpSalary::getEmpid, employeeMap.keySet());
        }
        if (StringUtils.isNotEmpty(salaryTO.getStartdate()) && StringUtils.isNotEmpty(salaryTO.getEnddate())) {
            empSalaryQueryWrapper.lambda().between(TlEmpSalary::getPaydate, AttributeUtils.timeCompletion(salaryTO.getStartdate(), 's'), AttributeUtils.timeCompletion(salaryTO.getEnddate(), 'e'));
        }
        if (salaryTO.getParams().containsKey("dataScope") && StringUtils.isNotEmpty(salaryTO.getParams().get("dataScope").toString())) {
            empSalaryQueryWrapper.lambda().apply(salaryTO.getParams().get("dataScope").toString());
        }
        empSalaryQueryWrapper.lambda().orderByDesc(TlEmpSalary::getCreatetime);
        List<TlEmpSalary> empSalaryList = tlEmpSalaryMapper.selectList(empSalaryQueryWrapper);
        employeeMap = employeeService.getEmpMap(new QueryWrapper<>());
        for (TlEmpSalary tlEmpSalary : empSalaryList) {
            if (employeeMap.containsKey(tlEmpSalary.getEmpid())) {
                tlEmpSalary.setEmpName(employeeMap.get(tlEmpSalary.getEmpid()).getName());
                tlEmpSalary.setIdcardnum(employeeMap.get(tlEmpSalary.getEmpid()).getIdcardnum());
                tlEmpSalary.setEmplnum(employeeMap.get(tlEmpSalary.getEmpid()).getEmplnum());
            }
            if (workTypeMap.containsKey(tlEmpSalary.getWorkType())) {
                tlEmpSalary.setWorkTypeName(workTypeMap.get(tlEmpSalary.getWorkType()).getWorktype());
            }
            if (operationMap.containsKey(tlEmpSalary.getOperationId())) {
                tlEmpSalary.setOperationName(operationMap.get(tlEmpSalary.getOperationId()).getOperationtype());
            }
            if (departMap.containsKey(tlEmpSalary.getEmpdeptid())) {
                tlEmpSalary.setEmpdeptName(departMap.get(tlEmpSalary.getEmpdeptid()).getDepartName());
            }
        }
        PageInfoConvent<TlEmpSalary> empSalaryPageInfoConvent = new PageInfoConvent<TlEmpSalary>(salaryTO.getPage().intValue(), salaryTO.getSize().intValue(), empSalaryList);
        json.put("total", empSalaryList.size());
        json.put("resultlist", empSalaryPageInfoConvent.getList());
        return json;
    }

    @Override
    public void excelReader(List<TlEmpSalary> empSalaryList) throws ExcelReaderDataException {

        String uid = LoginUtils.getUser().getUid();
        List<SysDepart> departList = departMapper.selectList(new QueryWrapper<>());
        List<TlEmployee> employeeList = employeeMapper.selectList(new QueryWrapper<>());
        Map<String, SysDepart> departMap = new HashMap<>();
        if (!departList.isEmpty()) {
            Predicate<SysDepart> departNameNotNull = depart -> StringUtils.isNotEmpty(depart.getDepartName());
            departList = departList.stream().filter(departNameNotNull).collect(Collectors.toList());
            departMap = GroupingByUtils.getGroupingForMapEntity(departList, SysDepart::getDepartName, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0)));
        }
        Map<String, TlEmployee> employeeMap = new HashMap<>();
        if (!departList.isEmpty()) {
            Predicate<TlEmployee> nameNotNull = employee -> StringUtils.isNotEmpty(employee.getName());
            employeeList = employeeList.stream().filter(nameNotNull).collect(Collectors.toList());
            employeeMap = GroupingByUtils.getGroupingForMapEntity(employeeList, TlEmployee::getName, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0)));
        }

        int num = 1;
        String str = "";
        for (TlEmpSalary empSalary : empSalaryList) {
            empSalary.setCreatetime(new Date());
            empSalary.setCreateby(uid);
            if (empSalary.getMonthDate() != null) {
                empSalary.setMonth(Tools.getYearMonthString(empSalary.getMonthDate()));
            }
            if (StringUtils.isNotEmpty(empSalary.getEmpdeptName())) {
                if (departMap.containsKey(empSalary.getEmpdeptName())) {
                    empSalary.setEmpdeptid(departMap.get(empSalary.getEmpdeptName()).getId());
                } else {
                    str += "第" + num + "条的“‘所属机构’:‘" + empSalary.getEmpdeptName() + "’”" + "不存在;##";
                }
            } else {
                str += "第" + num + "条的“所属机构”不能为空;##";
            }
            if (StringUtils.isNotEmpty(empSalary.getEmpName())) {
                if (employeeMap.containsKey(empSalary.getEmpName())) {
                    empSalary.setEmpid(employeeMap.get(empSalary.getEmpName()).getId());
                } else {
                    str += "第" + num + "条的“‘姓名’:‘" + empSalary.getEmpName() + "’”" + "不存在;##";
                }
            } else {
                str += "第" + num + "条的“姓名”不能为空;##";
            }
            if (Objects.isNull(empSalary.getTotalsalary())) {
                str += "第" + num + "条的“实发工资”不能为空;##";
            }
            if (Objects.isNull(empSalary.getPaydate())) {
                str += "第" + num + "条的“发放日期”格式不正确;##";
            }
            num++;
        }
        if (StringUtils.isNotEmpty(str)) {
            throw new ExcelReaderDataException("您导入的数据:##" + str);
        }
    }


    @Override
    @DataScope(deptAlias = "empdeptid", userAlias = "createby")
    public List<TlEmpSalary> getTlEmpSalary(EmpSalaryListTO empSalaryListTo, SimpleDateFormat format) throws ParseException {
        List<TlEmployee> employeeList = null;
        QueryWrapper<TlEmployee> employeeQueryWrapper = new QueryWrapper<>();
        QueryWrapper<TlEmpSalary> empSalaryQueryWrapper = new QueryWrapper<>();
        if (empSalaryListTo.getParams().containsKey("dataScope") && StringUtils.isNotEmpty((empSalaryListTo.getParams().get("dataScope").toString())))
        {
            empSalaryQueryWrapper.lambda().apply(empSalaryListTo.getParams().get("dataScope").toString());
        }
        if (StringUtils.isNotEmpty(empSalaryListTo.getFullName())) {
            employeeQueryWrapper.lambda().eq(TlEmployee::getName, empSalaryListTo.getFullName());
            employeeList = employeeMapper.selectList(employeeQueryWrapper);
            Map<String, TlEmployee> employeeMap = GroupingByUtils.getGroupingForMapEntity(employeeList, TlEmployee::getName,
                    Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0)));
            empSalaryQueryWrapper.lambda().in(TlEmpSalary::getEmpid, employeeMap.keySet());
        }
        if (StringUtils.isNotEmpty(empSalaryListTo.getIdCardNo())) {
            employeeQueryWrapper.lambda().eq(TlEmployee::getIdcardnum, empSalaryListTo.getIdCardNo());
            employeeList = employeeMapper.selectList(employeeQueryWrapper);
            Map<String, TlEmployee> employeeMap = GroupingByUtils.getGroupingForMapEntity(employeeList, TlEmployee::getIdcardnum,
                    Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0)));
            empSalaryQueryWrapper.lambda().in(TlEmpSalary::getEmpid, employeeMap.keySet());
        }
        if (StringUtils.isNotEmpty(empSalaryListTo.getJobNumber())) {
            employeeQueryWrapper.lambda().eq(TlEmployee::getEmplnum, empSalaryListTo.getJobNumber());
            employeeList = employeeMapper.selectList(employeeQueryWrapper);
            Map<String, TlEmployee> employeeMap = GroupingByUtils.getGroupingForMapEntity(employeeList, TlEmployee::getEmplnum,
                    Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0)));
            empSalaryQueryWrapper.lambda().in(TlEmpSalary::getEmpid, employeeMap.keySet());
        }
        if (empSalaryListTo.getIds() != null && !empSalaryListTo.getIds().isEmpty()) {
            empSalaryQueryWrapper.lambda().in(TlEmpSalary::getId, empSalaryListTo.getIds());
        }
        if (StringUtils.isNotEmpty(empSalaryListTo.getStartTime()) && StringUtils.isNotEmpty(empSalaryListTo.getEndTime())) {
            empSalaryQueryWrapper.lambda().ge(TlEmpSalary::getCreatetime, format.parse(empSalaryListTo.getStartTime()));
            empSalaryQueryWrapper.lambda().le(TlEmpSalary::getCreatetime, format.parse(empSalaryListTo.getEndTime()));
        }

        List<TlEmpSalary> empSalaryList = tlEmpSalaryMapper.selectList(empSalaryQueryWrapper);
        return empSalaryList;
    }
}
